package com.ifonly.ar.core;

import com.ifonly.ar.exections.SqlExecuteException;
import com.ifonly.ar.exections.TableMapException;

import java.sql.*;

/**
 * @author ifonly
 * @version 1.0 2015-12-07 00:36
 * @since JDK 1.6
 */
public class Executor {
    protected static ARTableMapper tableMapper = ARTableMapper.getInstance();

    protected static Table getTableInMapper(Class<? extends ARModel> clazz) {
        Table table = tableMapper.get(clazz);
        if (table == null) {
            throw new TableMapException("The class [" + clazz.getName() + "] does not mapping");
        }

        return table;
    }

    public static int insert(Connection conn, String sql, Object... params) {
        try {
            PreparedStatement ps = createPreparedStatement(conn, sql, params);
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw new SqlExecuteException(e);
        }
    }

    public static ResultSet insertReturnGeneratedKeys(Connection conn, String[] pks, String sql, Object... params) {
        try {
            PreparedStatement ps = createPreparedStatementReturnGeneratedKeys(conn, pks, sql, params);
            ps.executeUpdate();
            return ps.getGeneratedKeys();
        } catch (SQLException e) {
            throw new SqlExecuteException(e);
        }
    }

    public static int update(Connection conn, String sql, Object... params) {
        try {
            PreparedStatement ps = createPreparedStatement(conn, sql, params);
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw new SqlExecuteException(e);
        }
    }

    public static int delete(Connection conn, String sql, Object[] params) {
        try {
            PreparedStatement ps = createPreparedStatement(conn, sql, params);
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw new SqlExecuteException(e);
        }
    }

    public static ResultSet query(Connection conn, String sql, Object... params) {
        try {
            PreparedStatement ps = createPreparedStatement(conn, sql, params);
            return ps.executeQuery();
        } catch (SQLException e) {
            throw new SqlExecuteException(e);
        }
    }

    protected static PreparedStatement createPreparedStatement(Connection conn, String sql, Object... params) throws SQLException {
        PreparedStatement ps = conn.prepareStatement(sql);
        fillPreparedStatement(ps, params);
        return ps;
    }

    protected static PreparedStatement createPreparedStatementReturnGeneratedKeys(Connection conn, String[] pks, String sql, Object... params) throws SQLException {
        PreparedStatement ps;
        if (pks == null || pks.length == 0) {
            ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
        } else {
            ps = conn.prepareStatement(sql, pks);
        }
        fillPreparedStatement(ps, params);
        return ps;
    }

    protected static void fillPreparedStatement(PreparedStatement ps, Object... params) {
        if (params != null && params.length > 0) {
            try {
                for (int i = 0, len = params.length; i < len; i++) {
                    ps.setObject(i + 1, params[i]);
                }
            } catch (SQLException e) {
                throw new SqlExecuteException(e);
            }
        }
    }

}
